import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import weekday from 'dayjs/plugin/weekday';
import isBetween from 'dayjs/plugin/isBetween';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import duration from 'dayjs/plugin/duration';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import 'dayjs/locale/zh-cn';

// 扩展dayjs插件
dayjs.extend(relativeTime);
dayjs.extend(weekday);
dayjs.extend(isBetween);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
dayjs.extend(duration);
dayjs.extend(customParseFormat);
dayjs.locale('zh-cn');

/**
 * 格式化 ISO 时间字符串为 'YYYY-MM-DD HH:mm:ss'
 * @param value ISO 时间字符串
 * @param format 自定义格式，默认 'YYYY-MM-DD HH:mm:ss'
 */
export function format_datetime(
  value: Date | string,
  format = 'YYYY-MM-DD HH:mm:ss',
): string {
  if (!value) return '';
  return dayjs(value).format(format);
}

/**
 * 格式化日期为 'YYYY-MM-DD'
 * @param value 日期
 */
export function format_date(value: Date | string): string {
  if (!value) return '';
  return dayjs(value).format('YYYY-MM-DD');
}

/**
 * 格式化时间为 'HH:mm:ss'
 * @param value 时间
 */
export function format_time(value: Date | string): string {
  if (!value) return '';
  return dayjs(value).format('HH:mm:ss');
}

/**
 * 获取相对时间（如：2小时前、3天后）
 * @param value 日期
 */
export function format_relative_time(value: Date | string): string {
  if (!value) return '';
  return dayjs(value).fromNow();
}

/**
 * 获取日期的中文星期
 * @param value 日期
 */
export function get_weekday(value: Date | string): string | undefined {
  if (!value) return '';
  const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
  return weekdays[dayjs(value).weekday()];
}

/**
 * 获取日期的英文星期缩写
 * @param value 日期
 */
export function get_weekday_short(value: Date | string): string | undefined {
  if (!value) return '';
  const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  return weekdays[dayjs(value).weekday()];
}

/**
 * 获取月份的中文表示
 * @param value 日期
 */
export function get_month_chinese(value: Date | string): string | undefined {
  if (!value) return '';
  const months = ['一月', '二月', '三月', '四月', '五月', '六月', 
                  '七月', '八月', '九月', '十月', '十一月', '十二月'];
  return months[dayjs(value).month()];
}

/**
 * 获取季度
 * @param value 日期
 */
export function get_quarter(value: Date | string): number {
  if (!value) return 0;
  return Math.floor(dayjs(value).month() / 3) + 1;
}

/**
 * 获取季度的中文表示
 * @param value 日期
 */
export function get_quarter_chinese(value: Date | string): string {
  const quarter = get_quarter(value);
  return `第${quarter}季度`;
}

/**
 * 判断是否为工作日（周一到周五）
 * @param value 日期
 */
export function is_weekday(value: Date | string | any): boolean {
  if (!value) return false;
  const day = dayjs(value).weekday();
  return day >= 1 && day <= 5; // 1-5 表示周一到周五
}

/**
 * 判断是否为周末（周六或周日）
 * @param value 日期
 */
export function is_weekend(value: Date | string): boolean {
  if (!value) return false;
  const day = dayjs(value).weekday();
  return day === 0 || day === 6; // 0和6 表示周日和周六
}

/**
 * 计算两个日期之间的工作日天数
 * @param startDate 开始日期
 * @param endDate 结束日期
 */
export function get_weekdays_between(startDate: Date | string, endDate: Date | string): number {
  if (!startDate || !endDate) return 0;
  
  let count = 0;
  const start = dayjs(startDate);
  const end = dayjs(endDate);
  
  // 确保开始日期不大于结束日期
  if (start.isAfter(end)) {
    return get_weekdays_between(endDate, startDate);
  }
  
  let current = start;
  while (current.isSameOrBefore(end, 'day')) {
    if (is_weekday(current)) {
      count++;
    }
    current = current.add(1, 'day');
  }
  
  return count;
}

/**
 * 计算两个日期之间的天数差
 * @param startDate 开始日期
 * @param endDate 结束日期
 */
export function get_days_between(startDate: Date | string, endDate: Date | string): number {
  if (!startDate || !endDate) return 0;
  return Math.abs(dayjs(endDate).diff(dayjs(startDate), 'day'));
}

/**
 * 计算两个日期之间的小时数差
 * @param startDate 开始日期
 * @param endDate 结束日期
 */
export function get_hours_between(startDate: Date | string, endDate: Date | string): number {
  if (!startDate || !endDate) return 0;
  return Math.abs(dayjs(endDate).diff(dayjs(startDate), 'hour'));
}

/**
 * 计算两个日期之间的分钟数差
 * @param startDate 开始日期
 * @param endDate 结束日期
 */
export function get_minutes_between(startDate: Date | string, endDate: Date | string): number {
  if (!startDate || !endDate) return 0;
  return Math.abs(dayjs(endDate).diff(dayjs(startDate), 'minute'));
}

/**
 * 获取指定月份的第一天
 * @param year 年份
 * @param month 月份（1-12）
 */
export function get_first_day_of_month(year: number, month: number): Date {
  return dayjs(`${year}-${month}-01`).toDate();
}

/**
 * 获取指定月份的最后一天
 * @param year 年份
 * @param month 月份（1-12）
 */
export function get_last_day_of_month(year: number, month: number): Date {
  return dayjs(`${year}-${month}-01`).endOf('month').toDate();
}

/**
 * 获取指定年份和周数的周一日期
 * @param year 年份
 * @param week 周数（1-53）
 */
export function get_first_day_of_week(year: number, week: number): Date {
  return dayjs(`${year}-01-01`).add(week - 1, 'week').weekday(1).toDate();
}

/**
 * 获取指定年份和周数的周日日期
 * @param year 年份
 * @param week 周数（1-53）
 */
export function get_last_day_of_week(year: number, week: number): Date {
  return dayjs(`${year}-01-01`).add(week - 1, 'week').weekday(7).toDate();
}

/**
 * 获取日期所在年份的周数
 * @param value 日期
 */
export function get_week_of_year(value: Date | string): number {
  if (!value) return 0;
  return (dayjs(value) as any).week();
}

/**
 * 判断日期是否在指定范围内
 * @param date 要检查的日期
 * @param startDate 开始日期
 * @param endDate 结束日期
 */
export function is_date_between(
  date: Date | string,
  startDate: Date | string,
  endDate: Date | string,
): boolean {
  if (!date || !startDate || !endDate) return false;
  return dayjs(date).isBetween(startDate, endDate, 'day', '[]');
}

/**
 * 判断日期是否为今天
 * @param value 日期
 */
export function is_today(value: Date | string): boolean {
  if (!value) return false;
  return dayjs(value).isSame(dayjs(), 'day');
}

/**
 * 判断日期是否为昨天
 * @param value 日期
 */
export function is_yesterday(value: Date | string): boolean {
  if (!value) return false;
  return dayjs(value).isSame(dayjs().subtract(1, 'day'), 'day');
}

/**
 * 判断日期是否为明天
 * @param value 日期
 */
export function is_tomorrow(value: Date | string): boolean {
  if (!value) return false;
  return dayjs(value).isSame(dayjs().add(1, 'day'), 'day');
}

/**
 * 判断日期是否为本月
 * @param value 日期
 */
export function is_this_month(value: Date | string): boolean {
  if (!value) return false;
  return dayjs(value).isSame(dayjs(), 'month');
}

/**
 * 判断日期是否为本年
 * @param value 日期
 */
export function is_this_year(value: Date | string): boolean {
  if (!value) return false;
  return dayjs(value).isSame(dayjs(), 'year');
}

/**
 * 获取当前财政年度的开始日期（假设4月1日开始）
 * @param currentDate 当前日期，默认为今天
 */
export function get_fiscal_year_start(currentDate?: Date | string): Date {
  const date = currentDate ? dayjs(currentDate) : dayjs();
  const year = date.month() >= 3 ? date.year() : date.year() - 1; // 4月及以后属于下一年财政年度
  return dayjs(`${year}-04-01`).toDate();
}

/**
 * 获取当前财政年度的结束日期（假设3月31日结束）
 * @param currentDate 当前日期，默认为今天
 */
export function get_fiscal_year_end(currentDate?: Date | string): Date {
  const date = currentDate ? dayjs(currentDate) : dayjs();
  const year = date.month() >= 3 ? date.year() + 1 : date.year(); // 4月及以后属于下一年财政年度
  return dayjs(`${year}-03-31`).toDate();
}

/**
 * 格式化时间段为可读字符串
 * @param minutes 分钟数
 */
export function format_duration(minutes: number): string {
  if (!minutes || minutes <= 0) return '0分钟';
  
  const days = Math.floor(minutes / (24 * 60));
  const hours = Math.floor((minutes % (24 * 60)) / 60);
  const mins = minutes % 60;
  
  const parts = [];
  if (days > 0) parts.push(`${days}天`);
  if (hours > 0) parts.push(`${hours}小时`);
  if (mins > 0 || parts.length === 0) parts.push(`${mins}分钟`);
  
  return parts.join('');
}

/**
 * 获取指定日期范围内的工作日列表
 * @param startDate 开始日期
 * @param endDate 结束日期
 * @param excludeHolidays 是否排除节假日，默认为true
 */
export function get_weekdays_list(
  startDate: Date | string,
  endDate: Date | string,
  excludeHolidays = true,
): Date[] {
  if (!startDate || !endDate) return [];
  
  const result: Date[] = [];
  const start = dayjs(startDate);
  const end = dayjs(endDate);
  
  // 确保开始日期不大于结束日期
  if (start.isAfter(end)) {
    return get_weekdays_list(endDate, startDate, excludeHolidays);
  }
  
  let current = start;
  while (current.isSameOrBefore(end, 'day')) {
    if (is_weekday(current)) {
      // 这里可以添加节假日排除逻辑，需要节假日数据
      result.push(current.toDate());
    }
    current = current.add(1, 'day');
  }
  
  return result;
}

/**
 * 解析自定义格式的日期字符串
 * @param dateString 日期字符串
 * @param format 日期格式
 */
export function parse_custom_date(dateString: string, format: string): Date | null {
  if (!dateString) return null;
  const date = dayjs(dateString, format);
  return date.isValid() ? date.toDate() : null;
}

/**
 * 获取年龄
 * @param birthDate 出生日期
 * @param currentDate 当前日期，默认为今天
 */
export function get_age(birthDate: Date | string, currentDate?: Date | string): number {
  if (!birthDate) return 0;
  const current = currentDate ? dayjs(currentDate) : dayjs();
  return current.diff(dayjs(birthDate), 'year');
}

/**
 * 获取指定日期的月初和月末日期
 * @param value 日期
 */
export function get_month_range(value: Date | string): { start: Date; end: Date } {
  if (!value) return { start: new Date(), end: new Date() };
  const date = dayjs(value);
  return {
    start: date.startOf('month').toDate(),
    end: date.endOf('month').toDate(),
  };
}

/**
 * 获取指定日期的年初和年末日期
 * @param value 日期
 */
export function get_year_range(value: Date | string): { start: Date; end: Date } {
  if (!value) return { start: new Date(), end: new Date() };
  const date = dayjs(value);
  return {
    start: date.startOf('year').toDate(),
    end: date.endOf('year').toDate(),
  };
}

/**
 * 获取指定日期的周初和周末日期
 * @param value 日期
 */
export function get_week_range(value: Date | string): { start: Date; end: Date } {
  if (!value) return { start: new Date(), end: new Date() };
  const date = dayjs(value);
  return {
    start: date.weekday(1).toDate(), // 周一
    end: date.weekday(7).toDate(),   // 周日
  };
}

/**
 * 获取指定日期的季度初和季度末日期
 * @param value 日期
 */
export function get_quarter_range(value: Date | string): { start: Date; end: Date } {
  if (!value) return { start: new Date(), end: new Date() };
  const date = dayjs(value);
  const quarter = get_quarter(value);
  const year = date.year();
  
  const quarterStartMonth = (quarter - 1) * 3 + 1;
  const start = dayjs(`${year}-${quarterStartMonth}-01`);
  const end = start.add(2, 'month').endOf('month');
  
  return {
    start: start.toDate(),
    end: end.toDate(),
  };
}

/**
 * 添加工作日
 * @param value 日期
 * @param days 要添加的工作日数
 */
export function add_weekdays(value: Date | string, days: number): Date {
  if (!value) return new Date();
  let date = dayjs(value);
  let remainingDays = Math.abs(days);
  const isAdding = days > 0;
  
  if (!isAdding) {
    // 如果是减去工作日，则反向处理
    return subtract_weekdays(value, remainingDays);
  }
  
  while (remainingDays > 0) {
    date = date.add(1, 'day');
    if (is_weekday(date)) {
      remainingDays--;
    }
  }
  
  return date.toDate();
}

/**
 * 减去工作日
 * @param value 日期
 * @param days 要减去的工作日数
 */
export function subtract_weekdays(value: Date | string, days: number): Date {
  if (!value) return new Date();
  let date = dayjs(value);
  let remainingDays = Math.abs(days);
  
  while (remainingDays > 0) {
    date = date.subtract(1, 'day');
    if (is_weekday(date)) {
      remainingDays--;
    }
  }
  
  return date.toDate();
}

/**
 * 获取两个日期之间的节假日列表（需要节假日数据）
 * @param startDate 开始日期
 * @param endDate 结束日期
 * @param holidays 节假日数据，格式为 { 'YYYY-MM-DD': '节日名称' }
 */
export function get_holidays_between(
  startDate: Date | string,
  endDate: Date | string,
  holidays: Record<string, string> = {},
): Array<{ date: Date; name: string }> {
  if (!startDate || !endDate) return [];
  
  const result: Array<{ date: Date; name: string }> = [];
  const start = dayjs(startDate);
  const end = dayjs(endDate);
  
  // 确保开始日期不大于结束日期
  if (start.isAfter(end)) {
    return get_holidays_between(endDate, startDate, holidays);
  }
  
  let current = start;
  while (current.isSameOrBefore(end, 'day')) {
    const dateStr = current.format('YYYY-MM-DD');
    if (holidays[dateStr]) {
      result.push({
        date: current.toDate(),
        name: holidays[dateStr],
      });
    }
    current = current.add(1, 'day');
  }
  
  return result;
}
